﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

namespace Core.Utility.Helper
{
    /// <summary>
    /// NPOI插件处理Excel
    /// <para>|--DataTable|DataSet导出到Excel</para>   
    /// <para>|--|--若DataTable.TableName不为空，则使用DataTable.TableName 作为Excel的Sheet名</para>
    /// <para>|--|--若DataTable.TableName为空，则使用Sheet+DataTable的索引</para>
    /// <para>|--Excel导入到DataTable|DataSet Excel的Sheet名默认为DataTable.TableName</para>
    /// </summary>
    public static class NpoiHelper
    {
        /// <summary>
        /// 设置DataTable Column 的 Caption 值
        /// </summary>
        /// <param name="dtSource"></param>
        /// <param name="capitons"></param>
        public static void SetDataTableColumnsCaption(DataTable dtSource, Dictionary<string, string> capitons)
        {
            foreach (DataColumn dc in dtSource.Columns)
            {
                if (capitons.ContainsKey(dc.ColumnName.ToLower()))
                {
                    dc.Caption = capitons[dc.ColumnName.ToLower()];
                }
            }
        }


        /// <summary>
        /// 传入DataTable导出到Excel 不弹出保存对话框
        /// <para>|--DataTable.TableName默认为Sheet名，若无TableName默认使用Sheet1</para>  
        /// </summary>
        /// <param name="fileFullPath">
        /// <para>此路径为文件存储的全路径，格式形如 盘符:\文件名.文件扩展名</para>
        /// <para>导出的路径 .xls使用 03版excel  .xlsx使用高版本excel</para>
        /// </param>
        /// <param name="dataTable">数据</param>
        /// <param name="columnsCaptionIsTitle">DataTable的column Caption是否作为标题</param>
        /// <param name="isTitleShowDouble">是否同时存在 column Name 和   column Caption</param>
        /// <param name="fileOverride">文件存在是否覆盖，默认为true</param>
        /// <returns></returns>
        public static NpoiOperateResultData<string> DataTableExportExcelNoSaveFileDialog(
            string fileFullPath,
            DataTable dataTable,
            bool columnsCaptionIsTitle = false,
            bool isTitleShowDouble = false,
            bool fileOverride = true)
        {
            DataSet dsExport = new DataSet();
            dsExport.Tables.Add(dataTable.Copy());
            return DataSetExportExcelNoSaveFileDialog(fileFullPath,dsExport, columnsCaptionIsTitle, isTitleShowDouble,fileOverride);
        }

        /// <summary>
        /// 传入DataSet导出多个sheet的Excel 不弹出对话框
        /// <para>|--DataTable.TableName默认为Sheet名，若无TableName默认使用Sheet+DataTable在DataSet中的索引</para>
        /// </summary>
        /// <param name="fileFullPath">
        /// <para>此路径为文件存储的全路径，格式形如 盘符:\文件名.文件扩展名</para>
        /// <para>导出的路径 .xls使用 03版excel  .xlsx使用高版本excel</para>
        /// </param>
        /// <param name="dataSet">导出的数据集</param>
        /// <param name="columnsCaptionIsTitle">DataTable的column Caption是否作为标题</param>
        /// <param name="isTitleShowDouble">是否同时存在 column Name 和   column Caption</param>
        /// <param name="fileOverride">文件存在是否覆盖，默认为true</param>
        /// <returns></returns>
        public static NpoiOperateResultData<string> DataSetExportExcelNoSaveFileDialog(
            string fileFullPath, 
            DataSet dataSet, 
            bool columnsCaptionIsTitle = false,
            bool isTitleShowDouble = false,
            bool fileOverride = true)
        {

            NpoiOperateResultData<string> result = new NpoiOperateResultData<string>();

            if (File.Exists(fileFullPath))
            {
                if (!fileOverride)
                {
                    result.Message = $"文件：{fileFullPath} 已存在！";
                    return result;
                }
            }

            //用于写入文件
            //MemoryStream ms = new MemoryStream();
            try
            {
                IWorkbook? workbook = null;
                if (Path.GetExtension(fileFullPath).ToLower().Equals(".xls"))
                {
                    workbook = new HSSFWorkbook();
                }
                else
                {
                    workbook = new XSSFWorkbook();
                }

                if (dataSet != null)
                {
                    for (int dataTableIndex = 0; dataTableIndex < dataSet.Tables.Count; dataTableIndex++)
                    {
                        DataTable dataTable = dataSet.Tables[dataTableIndex];
                        if (dataTable != null)
                        {

                            //创建sheet
                            string sheetName = dataTable.TableName.Trim();
                            if (sheetName.Length <= 0)
                            {
                                sheetName = "Sheet" + dataTableIndex;
                            }
                            else
                            {
                                if (sheetName.Length > 30)
                                {
                                    sheetName = sheetName.Substring(0, 30);
                                }
                            }

                            CreateDefaultSheet(workbook,sheetName, dataTable, columnsCaptionIsTitle, isTitleShowDouble,fileFullPath);
                        }
                        else
                        {
                            //MessageBox.Show("没有要导出的数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                            result.Message = "没有要导出到Excel的数据!";
                        }

                    }
                    //from for(dataSet)
                    //if (fileByte != null)
                    //{
                    //    using (FileStream fileStream = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write))
                    //    {
                    //        byte[] data = fileByte;
                    //        fileStream.Write(data, 0, data.Length);
                    //        fileStream.Flush();
                    //        fileStream.Close();
                    //        fileStream.Dispose();
                    //    }
                    //}
                    //else
                    //{
                    //    result.Message = "没有要导出到Excel的数据!";
                    //}

                    workbook = null;
                    result.Message = "文件已导出到：" + fileFullPath;
                    result.Result = true;
                    result.FileFullPath = fileFullPath;
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Exception:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                result.Message = $"Excel文件导出失败！{ex.Message}";
                result.Exception = ex;
            }
            finally
            {
            }
            return result;
        }


        /// <summary>
        /// 将excel中的数据导入到DataTable中
        /// </summary>
        /// <param name="fileFullPath">
        /// <para>此路径为文件存储的全路径，格式形如 盘符:\文件名.文件扩展名</para>
        /// <para>导出的路径 .xls使用 03版excel  .xlsx使用高版本excel</para>
        /// </param>
        /// <param name="sheetName">Sheet名称,为空则读取所有，不为空则读取指定名称的Sheet，若指定名称的Sheet不存在，则尝试读取第一个</param>
        /// <param name="columnNameRowLine">列名行号，默认1, 小于等于 0 则不存在行号</param>
        /// <param name="isReadData">是否读取数据</param>
        /// <param name="isColumnNameTrim">列名是否去空格</param>
        /// <returns>返回的DataTable</returns>
        public static NpoiOperateResultData<DataTable> ExcelImportDataTableNoOpenFileDialog(string fileFullPath, string sheetName = "", int columnNameRowLine = 1, bool isColumnNameTrim = false,bool isReadData = true)
        {
            NpoiOperateResultData<DataTable> result = new NpoiOperateResultData<DataTable>
            {
                Data = new DataTable(),
                FileFullPath = fileFullPath
            };
            if (string.IsNullOrEmpty(fileFullPath))
            {
                result.Message = $"需要导入的文件路径不能为空！";
                return result;
            }
            if (!File.Exists(fileFullPath))
            {
                result.Message = $"文件：{fileFullPath} 在路径中不存在！";
                return result;
            }
            DataSet dsRes = new DataSet();//
            try
            {
                dsRes = ReadSheetToDataSet(fileFullPath, sheetName, columnNameRowLine, isColumnNameTrim, isReadData);
                result.Result = true;
                if (dsRes.Tables.Count > 0)
                {
                    result.Data = dsRes.Tables[0];
                }
                result.Message = "操作成功！";
            }
            catch (Exception ex)
            {
                result.Message = $"导入Excel文件：{fileFullPath} 失败！";
                result.Exception = ex;
            }
            return result;
        }

        /// <summary>
        /// 将excel中的数据导入到DataSet中
        /// </summary>
        /// <param name="fileFullPath">
        /// <para>此路径为文件存储的全路径，格式形如 盘符:\文件名.文件扩展名</para>
        /// <para>导出的路径 .xls使用 03版excel  .xlsx使用高版本excel</para>
        /// </param>
        /// <param name="sheetName">Sheet名称,为空则读取所有，不为空则读取指定名称的Sheet，若指定名称的Sheet不存在，则尝试读取第一个</param>
        /// <param name="columnNameRowLine">第一行是否是DataTable的列名</param>
        /// <param name="isReadData">是否读取数据</param>
        /// <param name="isColumnNameTrim">列名是否去空格</param>
        /// <returns>返回的DataSet</returns>
        public static NpoiOperateResultData<DataSet> ExcelImportDataSetNoOpenFileDialog(string fileFullPath, string sheetName = "", int columnNameRowLine = 1, bool isColumnNameTrim = false, bool isReadData = true)
        {
            NpoiOperateResultData<DataSet> result = new NpoiOperateResultData<DataSet>
            {
                Data = new DataSet(),
                FileFullPath = fileFullPath
            };
            if (string.IsNullOrEmpty(fileFullPath))
            {
                result.Message = $"需要导入的文件路径不能为空！";
                return result;
            }
            if (!File.Exists(fileFullPath))
            {
                result.Message = $"文件：{fileFullPath} 在路径中不存在！";
                return result;
            }
            DataSet dsRes = new DataSet();//
            try
            {
                dsRes = ReadSheetToDataSet(fileFullPath, sheetName, columnNameRowLine, isColumnNameTrim, isReadData);
                result.Result = true;
                result.Data = dsRes;
                result.Message = "操作成功！";
            }
            catch (Exception ex)
            {
                result.Message = $"导入Excel文件：{fileFullPath} 失败！";
                result.Exception = ex;
            }
            return  result;
        }
        
        /// <summary>
        /// 创建Sheet并填充数据
        /// </summary>
        /// <param name="workbook">工作表名称</param>
        /// <param name="sheetName">Sheet名称</param>
        /// <param name="dtData">填充的数据</param>
        /// <param name="columnsCaptionIsTitle">DataTable的column Caption是否作为标题</param>
        /// <param name="isTitleShowDouble">是否同时存在 column Name 和   column Caption,前提是都不为空</param>
        /// <param name="fileFullPath"></param>
        public static void CreateDefaultSheet(IWorkbook workbook,string sheetName, DataTable dtData, bool columnsCaptionIsTitle, bool isTitleShowDouble,string fileFullPath)
        {
            ISheet sheet = workbook.CreateSheet(sheetName);

            //添加表头
            IRow row = sheet.CreateRow(0);
            ICellStyle cellStyleTitle = workbook.CreateCellStyle();
            cellStyleTitle.WrapText = true;//设置换行
            int cellIndex = 0;
            foreach (DataColumn dc in dtData.Columns)
            {
                //创建列
                ICell cell = row.CreateCell(cellIndex);
                cell.SetCellType(CellType.String);
                if (isTitleShowDouble == false)
                {
                    if (columnsCaptionIsTitle)
                    {
                        if (!string.IsNullOrEmpty(dc.Caption))
                        {
                            cell.SetCellValue(dc.Caption);
                        }
                        else
                        {
                            cell.SetCellValue(dc.ColumnName);
                        }
                    }
                    else
                    {
                        cell.SetCellValue(dc.ColumnName);
                    }
                }
                else
                {
                    if (columnsCaptionIsTitle)
                    {
                        if (!string.IsNullOrEmpty(dc.Caption) && !string.IsNullOrEmpty(dc.ColumnName))
                        {
                            cell.SetCellValue(dc.Caption + "\n" + dc.ColumnName);
                        }
                        else if (!string.IsNullOrEmpty(dc.Caption) && string.IsNullOrEmpty(dc.ColumnName))
                        {
                            cell.SetCellValue(dc.Caption);
                        }
                        else if (string.IsNullOrEmpty(dc.Caption) && !string.IsNullOrEmpty(dc.ColumnName))
                        {
                            cell.SetCellValue(dc.ColumnName);
                        }
                        else
                        {
                            cell.SetCellValue("Cell " + cellIndex + " No Tite");
                        }
                    }
                    else
                    {
                        cell.SetCellValue(dc.ColumnName);
                    }
                }
                cell.CellStyle = cellStyleTitle;
                cellIndex++;
            }

            //添加数据
            int pageSize = 1000;
            for (int dataRowNum = 0; dataRowNum < dtData.Rows.Count; dataRowNum++)
            {
                cellIndex = 0;
                row = sheet.CreateRow(dataRowNum + 1);
                foreach (DataColumn dc in dtData.Columns)
                {
                    ICell cell = row.CreateCell(cellIndex);
                    cell.SetCellType(CellType.String);
                    cell.SetCellValue(Convert.ToString(dtData.Rows[dataRowNum][cellIndex]));
                    cellIndex++;
                }
                if ( (dataRowNum + 1) % pageSize == 0 || (dataRowNum + 1 >= dtData.Rows.Count ))
                {
                    FileMode fileMode = FileMode.Create;
                    if(dataRowNum + 1 > pageSize)
                    {
                        //第二次写入打开，进行追加
                        fileMode = FileMode.Open;
                    }
                    if((dataRowNum + 1 >= dtData.Rows.Count))
                    {
                        //最后一次操作
                        //设置列宽度自适应
                        for (int i = 0; i < dtData.Columns.Count; i++)
                        {
                            sheet.AutoSizeColumn(i);
                            //sheet.SetColumnWidth(i, 10 * 256);
                        }
                    }
                    //每间隔1000条写入文件
                    using (FileStream fileStream = new FileStream(fileFullPath, fileMode, FileAccess.Write))
                    {
                        workbook.Write(fileStream);
                    }
                }
            }
        }

        /// <summary>
        /// 读取Sheet数据
        /// </summary>
        /// <param name="fileFullPath">
        /// <para>此路径为文件存储的全路径，格式形如 盘符:\文件名.文件扩展名</para>
        /// <para>导出的路径 .xls使用 03版excel  .xlsx使用高版本excel</para></param>
        /// <param name="sheetName">Sheet名称,为空则读取所有，不为空则读取指定名称的Sheet，若指定名称的Sheet不存在，则尝试读取第一个</param>
        /// <param name="isReadData">是否读取数据</param>
        /// <param name="columnNameRowLine">列名行号，默认1, 小于等于 0 则不存在行号</param>
        /// <param name="isColumnNameTrim">列名是否去空格</param>
        /// <returns></returns>
        public static DataSet ReadSheetToDataSet(string fileFullPath, string sheetName = "", int columnNameRowLine = 1, bool isColumnNameTrim = false, bool isReadData = true)
        {
            DataSet dsImportData = new DataSet();
            try
            {
                NpoiOperateResultData<IWorkbook> readWorkbook = ReadWorkbook(fileFullPath);
                if (!readWorkbook.Result)
                {
                    throw new Exception(readWorkbook.Message, readWorkbook.Exception);
                }
                if (readWorkbook.Data != null)
                {
                    IWorkbook workbook = readWorkbook.Data;
                    //是否只读取第一个sheet
                    bool isOnlyReadSheet1 = false;
                    for (int iSheetNum = 0; iSheetNum < workbook.NumberOfSheets; iSheetNum++)
                    {
                        ISheet? sheet = null;
                        int startRow = 0;

                        DataTable dt = new DataTable();
                        if (!string.IsNullOrEmpty(sheetName))
                        {
                            sheet = workbook.GetSheet(sheetName);
                            if (sheet == null)
                            {
                                //如果没有找到指定的sheetName对应的sheet，则尝试获取第一个sheet
                                sheet = workbook.GetSheetAt(0);
                            }
                            isOnlyReadSheet1 = true;
                        }
                        else
                        {
                            sheet = workbook.GetSheetAt(iSheetNum);
                        }

                        if (sheet != null)
                        {
                            //列名索引
                            int columnNameRowIndex = 0;
                            //列名行号
                            if (columnNameRowLine > 0)
                            {
                                columnNameRowIndex = columnNameRowLine - 1;
                            }
                            else if (columnNameRowLine < 0)
                            {
                                columnNameRowIndex = 0;
                            }

                            if (isOnlyReadSheet1)
                            {
                                dt.TableName = sheetName;
                            }
                            else
                            {
                                dt.TableName = sheet.SheetName.Trim();
                            }

                            //初始行
                            IRow initRow = sheet.GetRow(columnNameRowIndex);
                            //初始行最后一个cell的编号 即总的列数
                            int cellCount = initRow.LastCellNum;

                            //初始行是否是DataTable的列名
                            if (columnNameRowLine > 0)
                            {
                                //给dt添加列
                                for (int i = initRow.FirstCellNum; i < cellCount; ++i)
                                {
                                    ICell cell = initRow.GetCell(i);
                                    if (cell != null)
                                    {
                                        string? cellValue = cell.StringCellValue;
                                        if (!string.IsNullOrEmpty(cellValue))
                                        {
                                            if (isColumnNameTrim)
                                            {
                                                cellValue = cellValue?.Trim();
                                            }
                                            DataColumn column = new DataColumn(cellValue);
                                            dt.Columns.Add(column);
                                        }
                                    }
                                }

                                startRow = columnNameRowIndex + 1;
                            }
                            else
                            {
                                for (int i = initRow.FirstCellNum; i < cellCount; ++i)
                                {
                                    DataColumn column = new DataColumn("col_" + i);
                                    dt.Columns.Add(column);
                                }

                                startRow = columnNameRowIndex;
                            }

                            //开始获取数据
                            if (isReadData)
                            {
                                //最后一行的标号
                                int rowCount = sheet.LastRowNum;
                                for (int i = startRow; i <= rowCount; ++i)
                                {
                                    IRow row = sheet.GetRow(i);
                                    if (row == null) continue; //没有数据的行默认是null　　　　　　　

                                    DataRow dataRow = dt.NewRow();
                                    for (int j = row.FirstCellNum; j < cellCount; ++j)
                                    {
                                        if (j < dt.Columns.Count)
                                        {
                                            if (row.GetCell(j) != null) //同理，没有数据的单元格都默认是null
                                                dataRow[j] = row.GetCell(j).ToString();
                                        }
                                    }

                                    dt.Rows.Add(dataRow);
                                }
                            }

                            //设置TableName
                            dt.TableName = sheet.SheetName;
                            dsImportData.Tables.Add(dt.Copy());
                            if (isOnlyReadSheet1)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Exception:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                throw new Exception("NOPI 导入出现错误：\r\n" + ex.Message,ex);
            }
            return dsImportData;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static CellType TypeToCellType(Type type)
        {
            CellType cellType = CellType.String;
            if (type == typeof(decimal)
                || type == typeof(float)
                || type == typeof(double)
                || type == typeof(int)
                || type == typeof(long)
                || type == typeof(float)
                || type == typeof(double)
                || type == typeof(uint)
                || type == typeof(ulong)
                || type == typeof(decimal?)
                || type == typeof(float?)
                || type == typeof(double?)
                || type == typeof(int?)
                || type == typeof(long?)
                || type == typeof(float?)
                || type == typeof(double?)
                || type == typeof(uint?)
                || type == typeof(ulong?)
                || type == typeof(DateTime) 
                || type == typeof(DateTime?))
            {
                cellType = CellType.Numeric;
            }
            else if (type == typeof(bool) || type == typeof(bool?))
            {
                cellType = CellType.Boolean;
            }
            return cellType;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cell"></param>
        /// <param name="type"></param>
        /// <param name="cellValue"></param>
        public static void SetCellValue(this ICell cell,Type type,object cellValue)
        {
            if (type == typeof(decimal)
                || type == typeof(float)
                || type == typeof(double)
                || type == typeof(int)
                || type == typeof(long)
                || type == typeof(float)
                || type == typeof(double)
                || type == typeof(uint)
                || type == typeof(ulong)
                || type == typeof(decimal?)
                || type == typeof(float?)
                || type == typeof(double?)
                || type == typeof(int?)
                || type == typeof(long?)
                || type == typeof(float?)
                || type == typeof(double?)
                || type == typeof(uint?)
                || type == typeof(ulong?))
            {
                cell.SetCellValue(ValueTypeConvertHelper.ToDouble(cellValue));
            }
            else if (type == typeof(bool) || type == typeof(bool?))
            {
                cell.SetCellValue(ValueTypeConvertHelper.ToBoolean(cellValue));
            }
            else if (type == typeof(DateTime)
                     || type == typeof(DateTime?))
            {
                cell.SetCellValue(ValueTypeConvertHelper.ToDateTime(cellValue));
            }
            else
            {
                cell.SetCellValue(ValueTypeConvertHelper.ToString(cellValue));
            }

            //if (cellType == CellType.Boolean)
            //{
            //    cell.SetCellValue(ValueTypeConvertHelper.ToBoolean(cellValue));
            //}
            //else if (cellType == CellType.Numeric)
            //{
            //    cell.SetCellValue(ValueTypeConvertHelper.ToDouble(cellValue));
            //}
            //else if (cellType == CellType.Error)
            //{
            //    try
            //    {
            //        cell.SetCellErrorValue(
            //            ValueTypeConvertHelper.ToByte(cellValue));
            //    }
            //    catch
            //    {

            //    }
            //}
            ////else if (cellType == CellType.Blank)
            ////{
            ////    cell.SetCellValue(ValueTypeConvertHelper.ToString(importData.Rows[rowNumber][cellIndex]));
            ////}
            //else if (cellType == CellType.Formula)
            //{
            //    cell.SetCellFormula(ValueTypeConvertHelper.ToString(cellValue));
            //}
            ////else if (cellType == CellType.Unknown)
            ////{
            ////    cell.SetCellValue(ValueTypeConvertHelper.ToString(importData.Rows[rowNumber][cellIndex]));
            ////}
            //else
            //{
            //    cell.SetCellValue(ValueTypeConvertHelper.ToString(cellValue));
            //}

        }

        /// <summary>
        /// 读取Excel，并返回为IWorkbook
        /// </summary>
        /// <param name="fileFullPath">
        /// <para>此路径为文件存储的全路径，格式形如 盘符:\文件名.文件扩展名</para>
        /// <para>导出的路径 .xls使用 03版excel  .xlsx使用高版本excel</para></param>
        /// <returns></returns>
        public static NpoiOperateResultData<IWorkbook> ReadWorkbook(string fileFullPath)
        {
            NpoiOperateResultData<IWorkbook> result = new NpoiOperateResultData<IWorkbook>
            {
                Data = null,
                FileFullPath = fileFullPath
            };

            if (string.IsNullOrEmpty(fileFullPath))
            {
                result.Message = "需要导入的文件路径不能为空";
                return result;
                //throw new Exception($"需要导入的文件路径不能为空！");
            }

            if (!File.Exists(fileFullPath))
            {
                result.Message = $"文件：{fileFullPath} 不存在！";
                return result;
                //throw new Exception($"文件：{fileFullPath} 在路径中不存在！");
            }

            string fileNameExtension = Path.GetExtension(fileFullPath).ToLower();
            if (!fileNameExtension.Equals(".xlsx") && !fileNameExtension.Equals(".xls"))
            {
                result.Message = $"文件名：{Path.GetFileName(fileFullPath)} 的扩展名 {fileNameExtension} 不是有效的 Excel文件，请查证！";
                return result;
                //throw new Exception(
                //    $"文件名：{Path.GetFileName(fileFullPath)} 的扩展名 {fileNameExtension} 不是有效的 Excel文件，请查证！");
            }

            try
            {
                using (var fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
                {
                    IWorkbook? workbook = null;
                    if (fileNameExtension.Equals(".xlsx"))
                    {
                        // 2007版本
                        workbook = new XSSFWorkbook(fs);
                    }
                    else //if (fileNameExtension.Equals(".xls"))
                    {
                        // 2003版本
                        workbook = new HSSFWorkbook(fs);
                    }
                    result.Result = true;
                    result.Message = "操作成功";
                    result.Data = workbook;
                    fs.Close();
                    fs.Dispose();
                }
            }
            catch (Exception ex)
            {
                result.Message = $"读取文件：{Path.GetFileName(fileFullPath)} 出现异常！\r\n{ex.Message}";
                result.Exception =  ex;
            }
            return result;
        }
    }

    /// <summary>
    /// NPOI操作结果数据
    /// <para>操作失败返回 false，若出现异常，并将异常信息赋值给Exception</para>
    /// </summary>
    public class NpoiOperateResultData<T>
    {
        /// <summary>
        /// 
        /// </summary>
        public bool Result = false;

        /// <summary>
        /// 文件完整路径
        /// </summary>
        public string FileFullPath = string.Empty;

        /// <summary>
        /// 返回文件名
        /// </summary>
        public string FileName
        {
            get
            {
                string res = string.Empty;
                if (!string.IsNullOrEmpty(FileFullPath))
                {
                    res = Path.GetFileName(FileFullPath);
                }

                return res;
            }
        }

        /// <summary>
        /// 返回文件名，不包含扩展名
        /// </summary>
        public string FileNameWithoutExtension
        {
            get
            {
                string res = string.Empty;
                if (!string.IsNullOrEmpty(FileFullPath))
                {
                    res = Path.GetFileNameWithoutExtension(FileFullPath);
                }

                return res;
            }
        }

        /// <summary>
        /// 返回文件名的扩展名
        /// </summary>
        public string FileNameExtension
        {
            get
            {
                string res = string.Empty;
                if (!string.IsNullOrEmpty(FileFullPath))
                {
                    res = Path.GetExtension(FileFullPath);
                }

                return res;
            }
        }

        /// <summary>
        /// 提示信息
        /// </summary>
        public string Message = "操作失败";

        /// <summary>
        /// 
        /// </summary>
        public Exception? Exception = null;

        /// <summary>
        /// 数据
        /// </summary>
        public T? Data = default(T);
    }
}
